home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 16
/
CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso
/
CUCD
/
Online
/
HBBS
/
Source
/
Node
/
Node_Input.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-09
|
67KB
|
2,359 lines
/*
Node_Input.c - written By Dominic Clifton, part of HydraBBS's Node program
(C) 1994-7 Dominic Clifton - Hydra/dAT - Deluxe Software
Primarly the code for checking input from the user/sysop and
handles door<->node communications.
*/
#define USE_BUILTIN_MATH
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <exec/types.h>
#include <libraries/locale.h>
#include <exec/memory.h>
#include <dos/dosextens.h>
#include <intuition/screens.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <diskfont/diskfont.h>
#include <utility/utility.h>
#include <graphics/gfxbase.h>
#include <devices/console.h>
#include <workbench/workbench.h>
#include <graphics/scale.h>
#include <clib/locale_protos.h>
#include <clib/exec_protos.h>
#include <clib/wb_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/diskfont_protos.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <libraries/reqtools.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/reqtools_protos.h>
#include "NodeGUI.h"
#define ClrSignal(s) SetSignal(0,s)
extern struct ReqToolsBase *ReqToolsBase;
extern ULONG InfoWinActive;
extern ULONG *rttags;
#include <hbbs/types.h>
#include <hbbs/errors.h>
#include <hbbs/access.h>
#include <hbbs/defines.h>
#include <hbbs/structures.h>
#include <hbbs/strings.h>
#include <hbbs/files.h>
#include <hbbs/ansi_codes.h>
#include <HBBS/Hbbscommon_protos.h>
#ifdef __SASC
#include <HBBS/hbbscommon_pragmas_sas.h>
#else
#include <HBBS/hbbscommon_pragmas_stc.h>
#endif
#include <HBBS/Hbbsnode_protos.h>
#ifdef __SASC
#include <HBBS/Hbbsnode_pragmas_sas.h>
#else
#include <HBBS/Hbbsnode_pragmas_stc.h>
#endif
//#include "Node_Console_Protos.h"
#include "Node_Serial_Protos.h"
#include "Node_Main_Protos.h"
#include "Node_Misc_Protos.h"
#include "Node_Input_Protos.h"
extern int N_NodeNum;
extern struct BBSGlobalData *BBSGlobal;
extern struct NodeData *N_ND;
extern struct Library *HBBSCommonBase;
extern struct Library *HBBSNodeBase;
extern struct List *HistoryList;
extern ULONG HistoryItems;
#include "/common/shared_protos.h"
void SetUpSigs( void )
{
// this routine sets up all the signals availiable so you can checksignal() them
// or wait() on them or whatever....
if (N_ND->NodeSettings.Iconified==FALSE)
N_ND->WinSig=DEF_WINSIG;
else
N_ND->WinSig=0L;
if (N_ND->InformationOpen)
N_ND->InfoWinSig=DEF_INFOWINSIG;
else
N_ND->InfoWinSig=0L;
if (N_ND->SettingsOpen)
N_ND->SettingsWinSig=DEF_SETTINGSWINSIG;
else
N_ND->SettingsWinSig=0L;
SetupConSerSigs();
N_ND->PortSig=DEF_PORTSIG;
N_ND->TimerSig=DEF_TIMERSIG;
}
void SetUpDoorSigs( void )
{
// this routine sets up all the signals availiable so you can checksignal() them
// or wait() on them or whatever....
if (N_ND->NodeSettings.Iconified==FALSE)
N_ND->WinSig=DEF_WINSIG;
else
N_ND->WinSig=0L;
if (N_ND->InformationOpen)
N_ND->InfoWinSig=DEF_INFOWINSIG;
else
N_ND->InfoWinSig=0L;
if (N_ND->SettingsOpen)
N_ND->SettingsWinSig=DEF_SETTINGSWINSIG;
else
N_ND->SettingsWinSig=0L;
N_ND->PortSig=DEF_PORTSIG;
N_ND->TimerSig=DEF_TIMERSIG;
}
void HandleMiscSigs( ULONG ReturnedSigs )
{
// this routine handles all stuff like the sysop clicking on the node window
// or closing the watch screen etc. etc...
ULONG class;
UWORD code;
struct Gadget *pgsel;
struct IntuiMessage *imsg;
if (ReturnedSigs & N_ND->WinSig)
{
while ((NodeWnd) && (imsg=GT_GetIMsg(NodeWnd->UserPort)))
{
class=imsg->Class;
code=imsg->Code;
pgsel=(struct Gadget *)imsg->IAddress; /* Only reference if it is a gadget message */
GT_ReplyIMsg(imsg);
ProcessWindowNodeWnd(class, code, pgsel);
}
}
if (ReturnedSigs & N_ND->ConWinSig)
{
while ((N_ND->ConWin) && (imsg=GT_GetIMsg(N_ND->ConWin->UserPort)))
{
class=imsg->Class;
code=imsg->Code;
pgsel=(struct Gadget *)imsg->IAddress; /* Only reference if it is a gadget message */
GT_ReplyIMsg(imsg);
ProcessConWindow(class, code, pgsel);
}
}
if (ReturnedSigs & N_ND->InfoWinSig)
{
while ((InfoWin) && (imsg=GT_GetIMsg(InfoWin->UserPort)))
{
class=imsg->Class;
code=imsg->Code;
pgsel=(struct Gadget *)imsg->IAddress; /* Only reference if it is a gadget message */
GT_ReplyIMsg(imsg);
ProcessWindowInfoWin(class, code, pgsel);
}
}
if (ReturnedSigs & N_ND->SettingsWinSig)
{
while ((SettingsWin) && (imsg=GT_GetIMsg(SettingsWin->UserPort)))
{
class=imsg->Class;
code=imsg->Code;
pgsel=(struct Gadget *)imsg->IAddress; /* Only reference if it is a gadget message */
GT_ReplyIMsg(imsg);
ProcessWindowSettingsWin(class, code, pgsel);
}
}
if (ReturnedSigs & N_ND->PortSig)
{
HandleMsg(); // node can only be closed by a message from the CONTROL program
}
if (ReturnedSigs & (1L << N_ND->OLMPort->mp_SigBit))
{
struct Message *Msg;
while (Msg=GetMsg(N_ND->OLMPort))
{
FreeVec(Msg);
}
}
}
ULONG WaitAllSigs(void)
{
return(Wait((1L << N_ND->OLMPort->mp_SigBit) | N_ND->SettingsWinSig | N_ND->InfoWinSig |N_ND->WinSig | N_ND->PortSig | N_ND->ConSig | N_ND->SerSig | N_ND->ConWinSig | N_ND->TimerSig));
}
#define KEY_NONE 0
#define KEY_ESCAPE 1
#define KEY_CSI 2
ULONG CheckCSI(UBYTE ch,ULONG wherefrom)
{
ULONG ReturnedSigs;
BOOL done=FALSE;
int csipos=0;
// int loop;
if ((N_ND->char1==27 && ch=='[') || (ch==155))
{
N_ND->char1=0;
while (!done)
{
// now, we have to be specific as to where we think the control sequence
// is coming from, for instance, say you had got the first byte of the
// control sequence from the serial port, you obviously wouldn't want
// any more of the control sequence coming from the console.. :-)
if (wherefrom==GET_SERIAL)
{
if (!N_ND->SerWaiting) SendSerReadData();
}
if (wherefrom==GET_CONSOLE)
{
if (!N_ND->ConWaiting && N_ND->ConOK) ConReadData(1); // we only want to do a char at a time...
}
SetUpSigs();
ReturnedSigs=WaitAllSigs();
// handlemiscsigs() MAY close the console window.. so be careful!
// also N_ND->RequestShutdown MIGHT get set if the sysop clicks close
// on the control panel, BUT if we are in the middle of an escape sequence
// we don't want to know.
HandleMiscSigs(ReturnedSigs);
while ( ((wherefrom==GET_SERIAL) && HandleSerSigs(ReturnedSigs)) ||
((wherefrom==GET_CONSOLE) && HandleConSigs(ReturnedSigs)) )
{
if ( N_ND->IBuffer[0]>=0x40 && N_ND->IBuffer[0] <=0x7E)
{
N_ND->csistring[csipos]=N_ND->IBuffer[0];
csipos++;
done=TRUE;
}
else
{
N_ND->csistring[csipos]=N_ND->IBuffer[0];
csipos++;
}
}
}
N_ND->csistring[csipos]=0; // null terminate str..
// note: csipos is same as doing strlen(N_ND->csistring)..
return(KEY_CSI);
}
else
{
if (ch==27)
{
N_ND->char1=27;
return(KEY_NONE);
}
}
if (N_ND->char1==27)
{
N_ND->char1=0;
return(KEY_ESCAPE);
}
return(KEY_NONE);
}
void handleescape( void )
{
// puts("Escape Pressed!");
}
// when writing data to the console or serial port we MUST use <ESC>[ and not 0x9B
// cos then only amiga's would understand it! :-) But hey! what a cool idea!
/* NOT USED ANYMORE! only getline used them and I've had to modify that too much!
void CursorLeft( short num )
{
UBYTE outstr[6]; // csi+3digits+ansi terminator+null terminator
sprintf(outstr,"\033[%dD",num);
PutText(outstr);
}
void CursorRight( short num )
{
UBYTE outstr[6]; // csi+3digits+ansi terminator+null terminator
sprintf(outstr,"\033[%dC",num);
PutText(outstr);
}
void DeleteChars( short num )
{
UBYTE outstr[6]; // csi+3digits+ansi terminator+null terminator
sprintf(outstr,"\033[%dP",num);
PutText(outstr);
}
void InsertChars( short num )
{
UBYTE outstr[6]; // csi+3digits+ansi terminator+null terminator
sprintf(outstr,"\033[%d@",num);
PutText(outstr);
}
*/
ULONG CheckFunctionKeys( void )
{
// this routine checks the function keys, and depending on the
// N_ND->LoginType it does certain things...
ULONG status=IN_NOTHING;
// puts(N_ND->csistring);
if (stricmp(N_ND->csistring,str_CSI_F7)==0)
{
HBBS_CleanupNodeConsoleWin();
}
else
if (stricmp(N_ND->csistring,str_CSI_F8)==0)
{
HBBS_ChangeConsoleMode(2); // swap between screen and window..
if ((N_ND->LoginType==LOGIN_NONE) && (N_ND->CurrentLine[0]==0)) status=IN_DISPLAYAWAIT;
}
else
if (N_ND->LoginType==LOGIN_NONE)
{
if (stricmp(N_ND->csistring,str_CSI_F1)==0) status=IN_LOGIN; // Local Login
if (stricmp(N_ND->csistring,str_CSI_F2)==0)
{
InitModem(); // Init Modem
}
if (stricmp(N_ND->csistring,str_CSI_F3)==0) status=IN_IMMEDIATE; // Answer Modem Now
if (stricmp(N_ND->csistring,str_CSI_F4)==0) status=IN_DISPLAYAWAIT; // re-display Awaitscreen
if (stricmp(N_ND->csistring,str_CSI_F5)==0) // toggle modem debug
{
N_ND->NodeDevice.ModemDebug=!N_ND->NodeDevice.ModemDebug;
}
if (stricmp(N_ND->csistring,str_CSI_F6)==0)
{
// we have to fool the system into thinking that there's someone
// logged in so that we can run the door! :-)
N_ND->LoginType=LOGIN_LOCAL;
N_ND->OnlineStatus=OS_ONLINE;
GoSystemDoor("ACCOUNTEDIT",NULL);
// but not forgetting to put it back to how it was..
N_ND->LoginType=LOGIN_NONE;
N_ND->OnlineStatus=OS_OFFLINE;
// and display the await screen again to tidy up..
status=IN_DISPLAYAWAIT;
}
if (stricmp(N_ND->csistring,str_CSI_F9)==0) status=IN_TERMINAL;
if (stricmp(N_ND->csistring,str_CSI_SF9)==0) status=IN_DIALOUT;
if (stricmp(N_ND->csistring,str_CSI_F10)==0) status=IN_SHUTDOWN;
}
else // Oooh someone's logged in and the sysop wants to do something to the user!
{
if (stricmp(N_ND->csistring,str_CSI_F1)==0)
{
// chat door running ?
if ((N_ND->ActiveDoor) && (iposition("SYSOPCHAT",N_ND->ActiveDoor->node.ln_Name)>=0))
{
status=IN_ENDCHAT;
}
else
{
GoSystemDoor("SYSOPCHAT",NULL);
status=IN_ENDCHAT;
}
}
else
if (stricmp(N_ND->csistring,str_CSI_F6)==0)
{
if ((N_ND->ActiveDoor) && (iposition("ACCOUNTEDIT",N_ND->ActiveDoor->node.ln_Name)<0))
{
GoSystemDoor("ACCOUNTEDIT","SYSOPONLY");
}
}
else
if (stricmp(N_ND->csistring,str_CSI_SF6)==0)
{
if ((N_ND->ActiveDoor) && (iposition("ACCOUNTEDIT",N_ND->ActiveDoor->node.ln_Name)<0))
{
GoSystemDoor("ACCOUNTEDIT","SYSOPONLY CALLONLY");
}
}
else
if (stricmp(N_ND->csistring,str_CSI_SF10)==0)
{
if (N_ND->LoginType==LOGIN_REMOTE) HangUp();
return(IN_LOSSCARRIER);
}
}
return(status);
}
/* see defines.h
#define GL_NONE 0 // default
#define GL_HISTORY 1 // if set history is enabled (up/down cursor keys)
#define GL_LINEWRAP 2 // if maxlen is reached then data back to the last ' ' character is copied to N_ND->CurrentLineWrap and returns immediately
#define GL_IMMEDIATE 4 // returns when maxlen is reached
#define GL_NORETURN 8 // does not print a cr+lf when a) reached maxlen or b) timeout or c) return press
#define GL_EDIT 16 // enables cursor left/right and backspace/delete
#define GL_DISPLAY 32 // display chars (don't specify for "Press [return] to contine" type prompts)
#define GL_SYSOP 64 // does not write to, or read from, the serial port
#define GL_USECHARS 128 // see N_ND->CharsAllowed
#define GL_NOBEEP 256 // use with GL_USECHARS if you don't want a beep when
// the presses a key not in N_ND->CharsAllowed
#define GL_NOOLM 512 // (No OLM) if set olm's will not inturrpt the user
#define GL_NODISTURB 1024// Lets you use things like "Enter ID: [ ]" with out the ] moving
#define GL_CVTUPPER 2048// converts input chars to uppercase as the keys are pressed!
*/
void ReDrawLine(ULONG Flags, int *xpos)
{
char cmovestr[20];
if (Flags & GL_DISPLAY)
{
// now move back to the start of the string and erase it,
// then print the new string
if (*xpos)
{
sprintf(cmovestr,"\033[%dD",*xpos);
}
if (Flags & GL_SYSOP)
{
if (*xpos) PutConText(cmovestr);
PutConText("\033[K");
PutConText(N_ND->CurrentLine);
}
else
{
if (*xpos) PutText(cmovestr);
PutText("\033[K");
PutText(N_ND->CurrentLine);
}
}
*xpos=strlen(N_ND->CurrentLine);
}
V_BOOL CheckRaw(ULONG Flags)
{
V_BOOL GotSomeData=FALSE;
N_ND->CurrentLine[0]=0;
N_ND->CurrentLine[1]=0;
if (!(Flags & CR_NOCONSOLE) && (N_ND->ConOK)) // fixed, 25/07/96
{
if (N_ND->ConWaiting) AbortConRead();
N_ND->ConRead->io_Command = CMD_READ;
N_ND->ConRead->io_Data = (APTR)N_ND->CurrentLine;
N_ND->ConRead->io_Length = 1;
ClrSignal(1L << N_ND->ConRPort->mp_SigBit);
SendIO((struct IORequest*)N_ND->ConRead);
if (CheckIO((struct IORequest*)N_ND->ConRead))
{
WaitIO((struct IORequest*)N_ND->ConRead);
if (N_ND->ConRead->io_Actual)
{
GotSomeData=TRUE;
N_ND->CurrentLine[2]=1;
}
}
else
{
AbortIO((struct IORequest*)N_ND->ConRead);
}
}
if (!((GotSomeData) || (Flags & CR_NOSERIAL)) && (N_ND->SerOK)) // fixed, 25/07/96
{
if (SerQueryData()>0)
{
WaitSerReadBlock(N_ND->CurrentLine,1);
GotSomeData=TRUE;
N_ND->CurrentLine[2]=2;
}
}
return((V_BOOL)GotSomeData);
}
ULONG Get_Line(ULONG Flags,char PasswordChar,ULONG MaxLen, ULONG Timeout, UBYTE *PromptStr)
{
char tmpstr[BIG_STR];
int editloop,editlen;
ULONG ReturnedSigs;
UBYTE CurrentChar[2]={0,0}; // 2 chars, use ¤tchar for null terminated string type..
int xpos=0;
ULONG csitype=0;
ULONG retval=IN_NOTHING; // this must NOT be returned to the caller!!!!!
struct TimerData *TD=NULL, // TD is used if a timeout is specified
*TO_TD=NULL, // used for Inactivity Disconnect
*TL_TD=NULL; // used for time remaining
BOOL AddOK;
char *strptr;
LONG HistoryNum=HistoryItems,OldHistNum=-1;
char cmovestr[20];
if (N_ND->NodeFlags & NFLG_CTRLC) N_ND->NodeFlags-=NFLG_CTRLC;
N_ND->CurrentLine[0]=0; // null terminate the string..
N_ND->CurrentLineWrap[0]=0; // null terminate the string..
if (MaxLen==0) MaxLen=LEN_CURRENTLINE;
if (PromptStr)
{
strNcpy(N_ND->CurrentLine,PromptStr,MaxLen);
if (PasswordChar) // Convert promptstr to a blanked out string..
{
for (editloop=0;N_ND->CurrentLine[editloop];editloop++)
{
if (Flags & GL_SYSOP)
{
PutConChar(PasswordChar);
}
else
{
PutChar(PasswordChar);
}
}
}
else
{
if (Flags & GL_SYSOP)
{
PutConText(N_ND->CurrentLine);
}
else
{
PutText(N_ND->CurrentLine);
}
}
xpos=strlen(N_ND->CurrentLine);
}
if ((N_ND->LoginType==LOGIN_REMOTE) && (CarrierLost())) retval=IN_LOSSCARRIER;
while (retval==IN_NOTHING)
{
// we only want to read the serial port if a) it's open and b) if we're
// still awaiting connect or someone is logged on..
if (N_ND->SerOK && N_ND->LoginType !=LOGIN_LOCAL && (!(Flags & GL_SYSOP)) && (!(N_ND->NodeFlags & NFLG_BLOCKSERIAL)))
{
if (!N_ND->SerWaiting) SendSerReadData();
}
// we ALWAYS want to read the console if the console window is open.
// cos the sysop might wanna do sommat!
if (!N_ND->ConWaiting && N_ND->ConOK) ConReadData(1);
// Submit Timer for Inactivity Disconnect..
if (!N_ND->NodeSettings.InactivityDisconnectOverride)
{
if (!(Flags & GL_NOINACTIVITY))
{
if (N_ND->User.Valid && !N_ND->RunningAwait)
{
TO_TD=SubmitTimer(N_ND->NodeTimer,N_ND->NodeSettings.InactivitySeconds,0);
}
}
}
// Submit Timer for time allowed to enter string without chars being pressed.
if (Timeout)
{
TD=SubmitTimer(N_ND->NodeTimer,Timeout,0);
}
// Submit Timer for time allowed to enter string without chars being pressed.
if (N_ND->User.Valid && !N_ND->RunningAwait)
{
if (N_ND->User.Acs.Data[ACS_UNLIMTIME]=='N' && HBBS_TimeLeft()+1>0)
{
TL_TD=SubmitTimer(N_ND->NodeTimer,HBBS_TimeLeft()+1 * 60,0);
}
}
SetUpSigs();
ClrSignal(N_ND->TimerSig); // if we don't do this we keep getting signals when nothing has happened.
// note: it took me ages to find this.... Argh! The symptom was that all the
// cpu time disappeared when the bbs was waiting for input :-)! The complete
// opposite of normal operation
ReturnedSigs=WaitAllSigs();
HandleMiscSigs(ReturnedSigs);
// check olm's ? *C* add an option/flag to NOT check for OLM's..
if ((!(N_ND->NodeFlags & NFLG_HANDLINGOLM)) && (!(Flags & GL_NOOLM)) && (ReturnedSigs & (1L << N_ND->OLMPort->mp_SigBit)) && (N_ND->NodeFlags & NFLG_OLMSWAITING))
{
GoSystemDoor("ReadOLM",NULL);
xpos=0;
ReDrawLine(Flags,&xpos);
}
if (TO_TD)
{
if (CheckTimer(N_ND->NodeTimer,TO_TD))
{
TO_TD=NULL;
PutText("\r\n\r\nInactivityTimeout!\r\n\r\n"); //*C* make configurable, add option for executing door.
GoSystemDoor("InactivityTimeout",NULL);
sprintf(tmpstr,"Inactivity Timeout after %d seconds",N_ND->NodeSettings.InactivitySeconds);
HBBS_AddToCallersLog(tmpstr);
N_ND->Actions[ACTN_INACTIVITYTIMEOUT]=ACTC_INACTIVITYTIMEOUT;
// do stuff needed for sucessful hanging up of phone (actually this just sets the
// os_onlinestatus, the door must check this...
DOOR_Goodbye();
DOOR_HangUp(); // *C* check this is needed
retval=IN_LOSSCARRIER;
}
else
{
// If we have an inactivity timer then we need to restart the timer
// as a key has been pressed
AbortTimer(N_ND->NodeTimer,TO_TD);
TO_TD=NULL;
}
}
if (TL_TD)
{
if (CheckTimer(N_ND->NodeTimer,TL_TD))
{
TL_TD=NULL;
retval=IN_TIMEOUT;
}
else
{
AbortTimer(N_ND->NodeTimer,TL_TD);
TL_TD=NULL;
}
}
if (Timeout && retval==IN_NOTHING)
{
if (TD)
{
if (CheckTimer(N_ND->NodeTimer,TD))
{
TD=NULL;
retval=IN_TIMEOUT;
if ((Flags & GL_DISPLAY) && !(Flags & GL_NORETURN))
{
if (Flags & GL_SYSOP)
{
PutConText("\r\n");
}
else
{
PutText("\r\n");
}
}
}
else
{
// a key has been pressed so restart timer for string entry.
AbortTimer(N_ND->NodeTimer,TD);
TD=NULL;
}
}
}
if (N_ND->RequestShutdown) retval=IN_SHUTDOWN;
if (N_ND->LoginType==LOGIN_REMOTE && CarrierLost()) retval=IN_LOSSCARRIER;
while (retval==IN_NOTHING && HandleConSerSigs(ReturnedSigs)) // swapped!
{
// key press, restart timer!
if (Timeout)
{
if (TD) AbortTimer(N_ND->NodeTimer,TD);
TD=SubmitTimer(N_ND->NodeTimer,Timeout,0);
}
// ok, we got some data from somehwere...
CurrentChar[0]=N_ND->IBuffer[0];
// checkcsi() needs to know EXACTLY where to look for incoming data
csitype=CheckCSI(CurrentChar[0],ReturnedSigs & N_ND->ConSig ? GET_CONSOLE : GET_SERIAL);
switch (csitype)
{
case KEY_CSI:
{
if (Flags & GL_EDIT)
{
if (strcmp(N_ND->csistring,str_CSI_CURSORLEFT)==0)
{
if (xpos>0)
{
xpos--;
if (Flags & GL_DISPLAY)
{
if (Flags & GL_SYSOP)
{
PutConText("\033[1D");
}
else
{
PutText("\033[1D");
// CursorLeft(1);
}
}
}
}
else
{
if (strcmp(N_ND->csistring,str_CSI_CURSORRIGHT)==0)
{
if (xpos<strlen(N_ND->CurrentLine))
{
xpos++;
if (Flags & GL_DISPLAY)
{
if (Flags & GL_SYSOP)
{
PutConText("\033[1C");
}
else
{
PutText("\033[1C");
// CursorRight(1);
}
}
}
}
else
{
if ((Flags & GL_HISTORY) && (HistoryItems>0))
{
if (strcmp(N_ND->csistring,str_CSI_CURSORUP)==0)
{
if (HistoryNum>0)
{
HistoryNum--;
}
}
if (strcmp(N_ND->csistring,str_CSI_CURSORDOWN)==0)
{
if (HistoryNum<HistoryItems)
{
HistoryNum++;
}
}
if (HistoryNum!=OldHistNum)
{
if (HistoryNum<HistoryItems)
{
strNcpy(N_ND->CurrentLine,HBBS_ListName(HistoryList,HistoryNum),MaxLen);
OldHistNum=HistoryNum;
}
else
{
N_ND->CurrentLine[0]=0; // erase the line.. :-)
HistoryNum=HistoryItems;
OldHistNum=-1;
}
ReDrawLine(Flags,&xpos);
}
}
}
}
}
retval=CheckFunctionKeys();
}
break;
case KEY_ESCAPE:
handleescape();
// CheckCSI will leave one the character following the escape key
// in the buffer. so reset out mini string again..
CurrentChar[0]=N_ND->IBuffer[0];
// no break so we process the next char as well..
case KEY_NONE:
if (N_ND->LoginType!=LOGIN_NONE || ReturnedSigs & N_ND->SerSig)
{
if (CurrentChar[0]>=0x20) // i.e. not unprintable or a control char..
{
if (CurrentChar[0]==127) // DEL
{
if (Flags & GL_EDIT)
{
editlen=strlen(N_ND->CurrentLine);
if (xpos!=editlen)
{
for (editloop=xpos;editloop<((editlen<MaxLen ? editlen:MaxLen));editloop++) // <= to copy the null terminator as well!
{
N_ND->CurrentLine[editloop]=N_ND->CurrentLine[editloop+1];
}
if (Flags & GL_DISPLAY)
{
if (Flags & GL_SYSOP)
{
PutConText("\033[1P");
}
else
{
PutText("\033[1P");
if (Flags & GL_NODISTURB)
{
if (xpos==MaxLen-1)
{
strcpy(cmovestr,"\033[@");
}
else
{
sprintf(cmovestr,"\033[%dC\033[@\033[%dD",MaxLen-xpos-1,MaxLen-xpos-1);
}
PutText(cmovestr);
}
}
}
}
}
}
else
{
if (Flags & GL_CVTUPPER) CurrentChar[0]=toupper(CurrentChar[0]);
AddOK=FALSE;
if (Flags & GL_USECHARS)
{
if (strchr(N_ND->CharsAllowed,CurrentChar[0]))
{
AddOK=TRUE;
}
else
{
// ooh, wrong char, lets do a beep..
if (!(Flags & GL_NOBEEP))
{
// but only if we're allowed to!
if (Flags & GL_SYSOP)
{
PutConChar(7); // 7 = BEEP char!
}
else
{
PutChar(7);
}
}
}
} else AddOK=TRUE;
if (AddOK)
{
// ok, no function key pressed, so add the char to the end of the string...
if ((editlen=strlen(N_ND->CurrentLine)) < (LEN_CURRENTLINE < MaxLen ? LEN_CURRENTLINE : MaxLen))
{
if (xpos==editlen) // tag char on end ?
{
xpos++;
strcat(N_ND->CurrentLine,CurrentChar);
if (Flags & GL_DISPLAY)
{
if (Flags & GL_SYSOP)
{
if (PasswordChar) PutConChar(PasswordChar); else PutConChar(CurrentChar[0]);
}
else
{
if (PasswordChar) PutChar(PasswordChar); else PutChar(CurrentChar[0]);
}
}
}
else
{
if (Flags & GL_EDIT)
{
// gotta insert char!
for (editloop=editlen+1; editloop>xpos ;editloop--) //+1 for null terminator
{
N_ND->CurrentLine[editloop]=N_ND->CurrentLine[editloop-1];
}
N_ND->CurrentLine[xpos]=CurrentChar[0];
if (Flags & GL_DISPLAY)
{
if (Flags & GL_SYSOP)
{
PutConText("\033[1@");
PutConChar(CurrentChar[0]);
}
else
{
PutText("\033[1@");
PutChar(CurrentChar[0]);
if (Flags & GL_NODISTURB)
{
sprintf(cmovestr,"\033[%dC\033[P\033[%dD",MaxLen-xpos-1,MaxLen-xpos-1);
PutText(cmovestr);
}
}
}
xpos++;
}
}
}
}
}
}
else
{
switch (CurrentChar[0])
{
case 13: // return
if ((Flags & GL_DISPLAY) && !(Flags & GL_NORETURN)) PutText(str_CRLF); // linefeed...
retval=IN_GOTLINE;
break;
case 27: //escape
handleescape();
break;
case 3: //ctrl+c
if (!(N_ND->NodeFlags & NFLG_CTRLC)) N_ND->NodeFlags+=NFLG_CTRLC;
break;
case 24: //ctrl+x, clear the line..
N_ND->CurrentLine[0]=0;
ReDrawLine(Flags,&xpos);
break;
case 8: //backspace
if (Flags & GL_EDIT)
{
if (xpos>0)
{
xpos--;
editlen=strlen(N_ND->CurrentLine);
for (editloop=xpos;editloop<editlen;editloop++) // <= to copy the null terminator as well!
{
N_ND->CurrentLine[editloop]=N_ND->CurrentLine[editloop+1];
}
if (Flags & GL_DISPLAY)
{
if (Flags & GL_SYSOP)
{
PutConText("\033[1D\033[1P");
}
else
{
if (Flags & GL_NODISTURB)
{
if (xpos==MaxLen-1)
{
strcpy(cmovestr,"\033[@");
}
else
{
sprintf(cmovestr,"\033[%dC\033[@\033[%dD",MaxLen-xpos-1,MaxLen-xpos-1);
}
PutText(cmovestr);
}
PutText("\033[1D\033[1P");
// CursorLeft(1);
// DeleteChars(1);
}
}
}
}
break;
}
}
}
break;
}
}
if (retval==IN_NOTHING)
{
if ((strlen(N_ND->CurrentLine)==MaxLen) && (Flags & GL_IMMEDIATE))
{
retval=IN_GOTLINE;
if (Flags & GL_LINEWRAP)
{
if (strptr=strrchr(N_ND->CurrentLine,' '))
{
if (Flags & GL_DISPLAY)
{
sprintf(cmovestr,"\033[%dD\033[K",strlen(N_ND->CurrentLine)-(strptr-N_ND->CurrentLine));
if (Flags & GL_SYSOP)
{
PutConText(cmovestr);
}
else
{
PutText(cmovestr);
}
}
strcpy(N_ND->CurrentLineWrap,strptr+1);
*strptr=0;
// *C* update the display!
}
}
if ((Flags & GL_DISPLAY) && !(Flags & GL_NORETURN)) PutText(str_CRLF); // linefeed...
}
}
}
AbortTimer(N_ND->NodeTimer,TD);
AbortTimer(N_ND->NodeTimer,TO_TD);
AbortTimer(N_ND->NodeTimer,TL_TD);
if (Flags & GL_HISTORY)
{
if (N_ND->CurrentLine[0])
{
if (!NewStrNode(N_ND->CurrentLine,HistoryList))
{
HistoryItems++;
}
}
}
if (retval==IN_LOSSCARRIER)
{
N_ND->OnlineStatus=OS_OFFLINE;
if (Flags & GL_DISPLAY) PutConText(str_CRLF);
}
return(retval);
}
void RunDoor(char *doorname,char *options,BOOL DebugMode,BOOL ASync)
{
// function to start a door
// *C* have timeout on door, check file exists before attempting to run it...
char cmd[BIG_STR],outstr[BIG_STR+300];
// sprintf(cmd,"%s %d %s",doorname,N_NodeNum,options ? options : "\0");
sprintf(outstr,"%d",N_NodeNum);
replace(cmd,doorname,"{O}",options ? options : ""); //replace won't work with a null string
replace(cmd,cmd,"{N}",outstr);
// if doorlog is on then write to the doorlog file!
if (N_ND->NodeSettings.DoorLog || N_ND->DoorLogOverride)
{
HBBS_GetDate(outstr);
strcat(outstr," ");
HBBS_GetTime(outstr+strlen(outstr));
sprintf(outstr+strlen(outstr)," Handle: %s, Conf: %s, Door: %s\n",N_ND->User.CallData.Handle,N_ND->CurrentConf ? N_ND->CurrentConf->node.ln_Name : "None Joined",cmd);
HBBS_AppendStrToFile(N_ND->NodeSettings.DoorLogFile,outstr);
}
if (DebugMode)
{
printf("DOOR DEBUG MODE ON - Start the door with the settings below!\n"
"==============================================================================\n"
"%s\n"
"==============================================================================\n",cmd);
}
else
{
HBBS_RunDOSCMD(cmd,ASync);
}
}
struct MsgPort* CreateDoorStartPort( void )
{
struct MsgPort *DP=NULL;
sprintf(N_ND->DoorStartPortName,"DoorStart_N%d_D%d",N_ND->NodeNum,N_ND->DoorsRunning+1);
DP=CreatePort(N_ND->DoorStartPortName,0);
return(DP);
}
BOOL CheckDoorStarted(struct MsgPort *DP,char *systemoptions)
{
struct DoorActivityMsg *DM;
BOOL retval=FALSE;
while (DM=(struct DoorActivityMsg *)GetMsg(DP))
{
N_ND->ActiveDoor->SystemOptions=systemoptions;
ReplyMsg((struct Message *)DM);
retval=TRUE;
}
return(retval);
}
void GoDoor(char *doorname,char *systemoptions,char *options,BOOL DebugMode)
{
ULONG ReturnedSigs;
struct DoorData *CurrentDoor;
struct TimerData *TD;
BOOL timeout,doorstarted;
struct MsgPort *DP;
char *clinesave=N_ND->CurrentLine; // save old line..
// *C* Why have I commented this out ? is it because of the {N} {O}'s etc... i think it might be!
// if (PathOK(doorname)) // does door exist ?
// {
// strcpy(N_ND->Action,"Loading Door!");
// DOOR_UpdateNodeStatus(UPD_ACTION);
if (N_ND->CurrentLine=AllocVec(LEN_CURRENTLINE,MEMF_PUBLIC))
{
N_ND->CurrentLine[0]=0;
if (TD=SubmitTimer(N_ND->NodeTimer,BBSGlobal->Door_Timeout,0))
{
timeout=FALSE;
doorstarted=FALSE;
if (DP=CreateDoorStartPort())
{
N_ND->ActiveDoor=NULL;
RunDoor(doorname,options,DebugMode,TRUE);
// strcpy(N_ND->Action,"Waiting For Door");
// DOOR_UpdateNodeStatus(UPD_ACTION);
do
{
Wait (1L<<DP->mp_SigBit | DEF_PORTSIG | DEF_TIMERSIG);
doorstarted=CheckDoorStarted(DP,systemoptions);
if (timeout=CheckTimer(N_ND->NodeTimer,TD))
{
TD=NULL;
}
} while(doorstarted==FALSE && timeout==FALSE);
DeletePort(DP);
if (timeout)
{
HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_DOORTIMEOUT,doorname,TYPE_WARNING);
}
else
{
if (TD) AbortTimer(N_ND->NodeTimer,TD);
strNcpy(N_ND->Action,N_ND->ActiveDoor->node.ln_Name,MAX_ACTION_LEN);
DOOR_UpdateNodeStatus(UPD_ACTION);
if (N_ND->ActiveDoor!=NULL)
{
// This next loop is essentially the main loop of the bbs when
// a door is running! :-)
// wait until the door stops!
CurrentDoor=N_ND->ActiveDoor;
do
{
SetUpDoorSigs();
ReturnedSigs=Wait(N_ND->ConWinSig |
N_ND->SettingsWinSig |
N_ND->InfoWinSig |
N_ND->WinSig |
N_ND->PortSig);
HandleMiscSigs(ReturnedSigs);
// while the door is started we should check for function key presses
// and so on... (which is handled by HandleDoorMsg())
// repeat wait loop until the door is finished, can detect by looking to see
// what the value of the door pointer is when it starts, and then keep comparing
// that to the the ActiveDoor pointer, if they differ the door has closed (as
// the ActiveDoor Pointer would point to a different door or to NULL...
} while (N_ND->ActiveDoor==CurrentDoor);
if (DebugMode)
{
printf("Door return: ");
puts(N_ND->DoorReturn);
}
}
}
}
else
{
if (TD) AbortTimer(N_ND->NodeTimer,TD);
}
}
FreeVec(N_ND->CurrentLine);
N_ND->CurrentLine=clinesave;
}
/* *C* Why have I commented this out ? .. because of the {x}'s you plonka!
}
else
{
sprintf(outstr,"The door file (%s) is missing!\r\n",doorname);
PutText(outstr);
HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_GENERAL,outstr,TYPE_WARNING);
}
*/
if (N_ND->ActiveDoor)
{
strNcpy(N_ND->Action,N_ND->ActiveDoor->node.ln_Name,MAX_ACTION_LEN);
DOOR_UpdateNodeStatus(UPD_ACTION);
}
}
void PrintList( struct List *list)
{
struct Node *node;
for (node = list->lh_Head ; node->ln_Succ ; node =node->ln_Succ)
{
puts(node->ln_Name);
}
}
void CheckDoorTypes(char *actualtype,char *cmd,char *options)
{
char tmpstr[BIG_STR],numstr[5];
sprintf(numstr,"%d",N_NodeNum);
replace(tmpstr,cmd,"{N}",numstr);
replace(tmpstr,tmpstr,"{O}",options);
if (stricmp(actualtype,"SCREEN")==0)
{
DisplayScreen(tmpstr);
}
else
{
if (stricmp(actualtype,"SSCREEN")==0)
{
DisplaySpecialScreen(tmpstr);
}
else
{
if (stricmp(actualtype,"CLS")==0)
{
PutText(ANSI_CLS);
}
else
{
if (stricmp(actualtype,"PAUSE")==0)
{
PausePrompt(tmpstr,0);
}
else
{
if (stricmp(actualtype,"ECHO")==0)
{
PutText(tmpstr);
PutText("\r\n");
}
else
{
if (stricmp(actualtype,"DOS")==0)
{
HBBS_RunDOSCMD(tmpstr,FALSE);
}
}
}
}
}
}
}
#define GOSYS_CONF 1
#define GOSYS_NODE 2
#define GOSYS_CMDS 3
V_BOOL GoSystemDoor( char *doorname, char *options )
{
/* must search the SYSTEM door list in the commands dir for first the conf,
then the node and finally the hbbs:commands directories.. when it finds
it it runs it, note that there may be more than one door to call at a time
as you may define more than one door for each system function. e.g.
Examine_Type_1=HBBS
Examine_DOOR_1=HBBS:Doors/User/Examine/Examine.HBBS
Examine_Param_1=
Examine_Type_2=HBBS
Examine_DOOR_2=HBBS:Doors/User/DIZTimeAdd/DIZTimeAdd.HBBS
Examine_Param_2=[=- Uploaded At HH:MM -=]
Examine_Type_3=HBBS
Examine_DOOR_3=HBBS:Doors/User/Sentby/Sentby.HBBS
Examine_Param_3=Sent,Cps,Node
note: if you have say Examine_Type_1 in hbbs:conferences/newuser/commands/system
and in hbbs:commands/system the set of commands in hbbs:commands/system WILL NOT
be run as the former file has priority over the latter.
*/
UBYTE filename[BIG_STR],*optionname,*actualparam=NULL,*actualtype=NULL;
V_BOOL done=FALSE,DebugMode;
short whichfile;
struct CfgFileData *CfgFile;
struct List *CmdList=NULL;
struct Node *node;
short doornum;
N_ND->DoorReturn[0]=0; // null terminate string...
N_ND->DoorContinue=TRUE;
for (whichfile=GOSYS_CONF;whichfile<=GOSYS_CMDS && !done;whichfile++)
{
// if (stricmp("AWAIT",doorname)!=0 && stricmp("ACCOUNTEDIT",doorname)!=0 && N_ND->OnlineStatus==OS_OFFLINE)
// {
// done=TRUE;
// }
// else
// {
filename[0]=0;
switch(whichfile)
{
case GOSYS_CONF:
if (N_ND->CurrentConf) // have we joined a conf yet ?
{
strcpy(filename,N_ND->CurrentConf->ConfPath);
strcat(filename,FILENAME_CMDSSYSTEM);
}
break;
case GOSYS_NODE:
strcpy(filename,N_ND->NodeLocation);
strcat(filename,FILENAME_CMDSSYSTEM);
break;
case GOSYS_CMDS:
strcpy(filename,FILE_HBBS);
strcat(filename,FILENAME_CMDSSYSTEM);
break;
}
if (filename[0]) // string present ?
{
if (optionname=AllocVec(strlen(doorname)+10,MEMF_PUBLIC))
{
strcpy(optionname,doorname);
strcat(optionname,"_Door");
if (CfgFile=HBBS_LoadConfig(filename,LCFG_NONE))
{
if (HBBS_GetSetting(CfgFile,(void *)&CmdList,VTYPE_STRINGLIST,optionname,OPT_MULTI))
{
for (doornum=1,node = CmdList->lh_Head ; N_ND->DoorContinue && node->ln_Succ ; node =node->ln_Succ,doornum++)
{
actualtype=NULL;
sprintf(optionname,"%s_Type_%d",doorname,doornum);
if (HBBS_GetSetting(CfgFile,(void *)&actualtype,VTYPE_STRING,optionname,OPT_SINGLE))
{
actualparam=NULL;
sprintf(optionname,"%s_Param_%d",doorname,doornum);
HBBS_GetSetting(CfgFile,(void *)&actualparam,VTYPE_STRING,optionname,OPT_SINGLE);
if (!actualparam) actualparam=DupStr("");
if (actualparam)
{
done=TRUE;
DebugMode=FALSE;
sprintf(optionname,"%s_Debug_%d",doorname,doornum);
HBBS_GetSetting(CfgFile,(void *)&DebugMode,VTYPE_BOOL,optionname,OPT_SINGLE);
if (stricmp(actualtype,"HBBS")==0) //changed from "NORMAL" on 1-JULY-96
{
GoDoor(node->ln_Name,actualparam,options,DebugMode);
}
else
{
if (stricmp(actualtype,"CLI")==0)
{
RunDoor(node->ln_Name,options,DebugMode,FALSE);
}
else
{
CheckDoorTypes(actualtype,node->ln_Name,options);
}
}
FreeStr(actualparam);
}
FreeStr(actualtype);
}
}
FreeStrList(CmdList);
}
HBBS_FlushConfig(CfgFile);
}
FreeVec(optionname);
}
}
// }
}
return(done);
}
short WhatAccessNode(V_SMALLNUM accesslevel)
{
// returns the struct node number of the specified access level
// mainly used when you want to find the name of an access level
short retval=-1;
char tmpstr[10];
short loop;
struct Node *node;
sprintf(tmpstr,"%d",accesslevel);
for (loop=0,node = BBSGlobal->AcsLevelList->lh_Head ; node->ln_Succ && retval==-1 ; node =node->ln_Succ,loop++)
{
if (strcmp(tmpstr,node->ln_Name)==0)
{
retval=loop;
}
}
return(retval);
}
#define GOUSER_CONF 1
#define GOUSER_NODE 2
#define GOUSER_CMDS 3
V_BOOL GoUserDoor( char *doorname, char *options )
{
/* this door must first determine the current access level, then scan the following
files to find out what door to run.
CurrentConf/Commands/Level_XX
CurrentConf/Commands/AllLevels
Currentnode/Commands/Level_XX
Currentnode/Commands/AllLevels
HBBS:Commnds/Level_XX
HBBS:Commnds/AllLevels
then when it finds the door to run it calls it up!
*/
UBYTE dirname[BIG_STR],filename[BIG_STR],*optionname,*actualparam=NULL,*actualtype=NULL;
V_BOOL done=FALSE,DebugMode,SearchedAll;
short whichfile;
struct CfgFileData *CfgFile;
struct List *CmdList=NULL;
struct Node *node;
short doornum,CurrentAccess;
N_ND->DoorReturn[0]=0; // null terminate string...
N_ND->DoorContinue=TRUE;
for (whichfile=GOUSER_CONF;whichfile<=GOUSER_CMDS && !done;whichfile++)
{
dirname[0]=0;
filename[0]=0;
switch(whichfile)
{
case GOUSER_CONF:
if (N_ND->CurrentConf) // have we joined a conf yet ?
{
sprintf(dirname,"%sCommands/",N_ND->CurrentConf->ConfPath);
}
break;
case GOUSER_NODE:
sprintf(dirname,"%sCommands/",N_ND->NodeLocation);
break;
case GOUSER_CMDS:
strcpy(dirname,"HBBS:Commands/");
break;
}
if (dirname[0]) // string present ? cos it might not be if we ain't in a conf..
{
// ok, no we know where to look for the commands, so we gotta check
// "Level_<access>" downto "Level_00" until we find it, if it ain't there then
// we have to check "All_Levels"
SearchedAll=FALSE;
CurrentAccess=WhatAccessNode(N_ND->User.CallData.Access);
do
{
if (CurrentAccess<0)
{
sprintf(filename,"%sAll_Levels",dirname);
SearchedAll=TRUE;
}
else
{
node=GetNode(BBSGlobal->AcsLevelList,CurrentAccess);
sprintf(filename,"%sLevel_%s",dirname,node->ln_Name);
}
if (optionname=AllocVec(strlen(doorname)+10,MEMF_PUBLIC))
{
sprintf(optionname,"%s_Door",doorname);
if (CfgFile=HBBS_LoadConfig(filename,LCFG_NONE))
{
if (HBBS_GetSetting(CfgFile,(void *)&CmdList,VTYPE_STRINGLIST,optionname,OPT_MULTI))
{
for (doornum=1,node = CmdList->lh_Head ; N_ND->DoorContinue && node->ln_Succ ; node =node->ln_Succ,doornum++)
{
actualtype=NULL;
sprintf(optionname,"%s_Type_%d",doorname,doornum);
if (HBBS_GetSetting(CfgFile,(void *)&actualtype,VTYPE_STRING,optionname,OPT_SINGLE))
{
actualparam=NULL;
sprintf(optionname,"%s_Param_%d",doorname,doornum);
HBBS_GetSetting(CfgFile,(void *)&actualparam,VTYPE_STRING,optionname,OPT_SINGLE);
if (!actualparam) actualparam=DupStr("");
if (actualparam)
{
DebugMode=FALSE;
if (stricmp(actualtype,"HBBS")==0)
{
sprintf(optionname,"%s_Debug_%d",doorname,doornum);
HBBS_GetSetting(CfgFile,(void *)&DebugMode,VTYPE_BOOL,optionname,OPT_SINGLE);
GoDoor(node->ln_Name,actualparam,options,DebugMode);
}
else
{
if (stricmp(actualtype,"CLI")==0)
{
RunDoor(node->ln_Name,options,DebugMode,FALSE);
}
else
{
CheckDoorTypes(actualtype,node->ln_Name,options);
}
}
FreeStr(actualparam);
}
FreeStr(actualtype);
}
}
FreeStrList(CmdList);
done=TRUE;
}
HBBS_FlushConfig(CfgFile);
}
FreeVec(optionname);
}
CurrentAccess--;
} while (!( done || SearchedAll));
}
}
return(done);
}
// *M* Move routines into HBBSNode.C
void Add_Last_Caller(char *data)
{
struct Node *node;
if (N_ND->Current_Last_Callers==N_ND->Max_Last_Callers) // *C* make configurable
{
node=RemTail(N_ND->Last_Callers);
FreeStr(node->ln_Name);
FreeVec(node);
N_ND->Current_Last_Callers--;
}
if (node=(struct Node*)AllocVec(sizeof(struct Node),MEMF_PUBLIC|MEMF_CLEAR))
{
node->ln_Name=DupStr(data);
AddHead(N_ND->Last_Callers,node);
N_ND->Current_Last_Callers++;
}
UpdateInfoWin();
SendRequest(REQ_UPDATEINFO);
}
void Add_Last_PWFail(char *data)
{
struct Node *node;
if (N_ND->Current_Last_PWFails==N_ND->Max_Last_PWFails)
{
node=RemTail(N_ND->Last_PWFails);
FreeStr(node->ln_Name);
FreeVec(node);
N_ND->Current_Last_PWFails--;
}
if (node=(struct Node*)AllocVec(sizeof(struct Node),MEMF_PUBLIC|MEMF_CLEAR))
{
node->ln_Name=DupStr(data);
AddHead(N_ND->Last_PWFails,node);
N_ND->Current_Last_PWFails++;
}
UpdateInfoWin();
SendRequest(REQ_UPDATEINFO);
}
void Add_Last_Download(char *data)
{
struct Node *node;
if (N_ND->Current_Last_Downloads==N_ND->Max_Last_Downloads)
{
node=RemTail(N_ND->Last_Downloads);
FreeStr(node->ln_Name);
FreeVec(node);
N_ND->Current_Last_Downloads--;
}
if (node=(struct Node*)AllocVec(sizeof(struct Node),MEMF_PUBLIC|MEMF_CLEAR))
{
node->ln_Name=DupStr(data);
AddHead(N_ND->Last_Downloads,node);
N_ND->Current_Last_Downloads++;
}
UpdateInfoWin();
SendRequest(REQ_UPDATEINFO);
}
void Add_Last_Upload(char *data)
{
struct Node *node;
if (N_ND->Current_Last_Uploads==N_ND->Max_Last_Uploads)
{
node=RemTail(N_ND->Last_Uploads);
FreeStr(node->ln_Name);
FreeVec(node);
N_ND->Current_Last_Uploads--;
}
if (node=(struct Node*)AllocVec(sizeof(struct Node),MEMF_PUBLIC|MEMF_CLEAR))
{
node->ln_Name=DupStr(data);
AddHead(N_ND->Last_Uploads,node);
N_ND->Current_Last_Uploads++;
}
UpdateInfoWin();
SendRequest(REQ_UPDATEINFO);
}
#define DSS_CONF 1
#define DSS_NODE 2
#define DSS_HBBS 3
#define DSS_ERR 4
V_BOOL DisplaySpecialScreen(char *ScreenName)
{
char filename[BIG_STR];
BOOL TriedAllLevels,Done=FALSE;
struct Node *node;
short whichdir=DSS_CONF;
short CurrentAccess;
do
{
filename[0]=0;
if (N_ND->User.Valid)
{
TriedAllLevels=FALSE;
CurrentAccess=WhatAccessNode(N_ND->User.CallData.Access);
}
else
{
CurrentAccess=-1;
}
do
{
switch(whichdir)
{
case DSS_CONF:
if (N_ND->CurrentConf)
{
strcpy(filename,N_ND->CurrentConf->ConfPath);
}
break;
case DSS_NODE:
strcpy(filename,N_ND->NodeLocation);
break;
case DSS_HBBS:
strcpy(filename,"HBBS:");
break;
}
if (filename)
{
if (CurrentAccess<0) TriedAllLevels=TRUE;
strcat(filename,DIRNAME_SCREENSSPECIAL);
strcat(filename,ScreenName);
if (N_ND->User.Valid && !TriedAllLevels)
{
// add access level _XX here..
node=GetNode(BBSGlobal->AcsLevelList,CurrentAccess);
CurrentAccess--;
strcat(filename,"_");
strcat(filename,node->ln_Name);
}
if (N_ND->User.Valid)
{
node=GetNode(BBSGlobal->LanguageExtn,N_ND->User.CallData.Language-1); //offset starts at 1
}
else
{
node=BBSGlobal->LanguageExtn->lh_Head;
}
strcat(filename,node->ln_Name); // Change To Users Selected lanuage type
Done=DisplayScreen(filename);
} else TriedAllLevels=TRUE;
} while (!TriedAllLevels && !Done);
whichdir++;
} while (! ((Done) || (whichdir==DSS_ERR)) );
return(Done);
}
void SaveFileTags( void )
{
struct CfgFileData *cfgfile;
char tmpstr[BIG_STR];
char optionstr[20];
struct TaggedFile *filetagnode;
int loop=0;
sprintf(tmpstr,"HBBS:System/Data/Users/%d/TaggedFiles.CFG",N_ND->User.CallData.UserID);
if (cfgfile=HBBS_CreateConfig(tmpstr))
{
// this item is ignored, it's just for the sysop's benefit so he can look at a file and see whose tags are in it..
HBBS_AddCfgItem(cfgfile,"UserName",N_ND->User.CallData.Handle);
for (filetagnode = (struct TaggedFile *)N_ND->TaggedFileList->lh_Head ; filetagnode->node.ln_Succ ; filetagnode =(struct TaggedFile*)filetagnode->node.ln_Succ)
{
loop++;
if (filetagnode=(struct TaggedFile *)GetNode(N_ND->TaggedFileList,loop-1)) // get the node
{
sprintf(optionstr,"FileName_%d",loop);
HBBS_AddCfgItem(cfgfile,optionstr,filetagnode->node.ln_Name);
sprintf(optionstr,"WarezFile_%d",loop);
HBBS_AddCfgItem(cfgfile,optionstr,filetagnode->WarezFile ? "YES" : "NO");
sprintf(optionstr,"ConferenceNum_%d",loop);
sprintf(tmpstr,"%d",filetagnode->ConferenceNum);
HBBS_AddCfgItem(cfgfile,optionstr,tmpstr);
sprintf(optionstr,"FileSize_%d",loop);
sprintf(tmpstr,"%d",filetagnode->FileSize);
HBBS_AddCfgItem(cfgfile,optionstr,tmpstr);
}
}
HBBS_SaveConfig(cfgfile);
HBBS_FlushConfig(cfgfile);
}
}
void LoadFileTags( void )
{
struct CfgFileData *cfgfile;
char tmpstr[BIG_STR];
char optionstr[20];
char *strptr;
struct TaggedFile *filetagnode;
BOOL Error=FALSE;
N_ND->TaggedFiles=0;
// reinitialise list..
NewList(N_ND->TaggedFileList);
sprintf(tmpstr,"HBBS:System/Data/Users/%d/TaggedFiles.CFG",N_ND->User.CallData.UserID);
if (cfgfile=HBBS_LoadConfig(tmpstr,LCFG_NONE))
{
do
{
Error=TRUE;
strptr=NULL;
sprintf(optionstr,"FileName_%d",N_ND->TaggedFiles+1);
if (HBBS_GetSetting(cfgfile,(void *)&strptr,VTYPE_STRING,optionstr,OPT_SINGLE))
{
if (filetagnode=AllocVec(sizeof(struct TaggedFile),MEMF_PUBLIC))
{
N_ND->TaggedFiles++;
filetagnode->node.ln_Name=strptr;
sprintf(optionstr,"WarezFile_%d",N_ND->TaggedFiles);
if (HBBS_GetSetting(cfgfile,(void *)&filetagnode->WarezFile,VTYPE_BOOL,optionstr,OPT_SINGLE))
{
sprintf(optionstr,"ConferenceNum_%d",N_ND->TaggedFiles);
if (HBBS_GetSetting(cfgfile,(void *)&filetagnode->ConferenceNum,VTYPE_BIGNUM,optionstr,OPT_SINGLE))
{
sprintf(optionstr,"FileSize_%d",N_ND->TaggedFiles);
if (HBBS_GetSetting(cfgfile,(void *)&filetagnode->FileSize,VTYPE_BIGNUM,optionstr,OPT_SINGLE))
{
Error=FALSE;
AddTail(N_ND->TaggedFileList,(struct Node*) filetagnode);
}
}
}
if (Error)
{
FreeStr(strptr);
FreeVec(filetagnode);
N_ND->TaggedFiles--;
}
}
}
} while (Error==FALSE);
HBBS_FlushConfig(cfgfile);
}
}
void ResetVars( void )
{
LONG loop;
char tmpfilename[BIG_STR];
for (loop=0;loop<LEN_ACTIONS;loop++)
{
N_ND->Actions[loop]=ACTC_NONE;
}
N_ND->Actions[LEN_ACTIONS]=0;
N_ND->NodeFlags=NFLG_NONE;
N_ND->User.Valid=FALSE;
N_ND->Action[0]=0;
N_ND->DoorReturn[0]=0;
N_ND->CurrentLine[0]=0;
N_ND->CurrentLineWrap[0]=0;
N_ND->CurrentConf=NULL;
N_ND->MaxDIZLines=N_ND->NodeSettings.MaxDIZLines;
N_ND->User.FilesUploaded=0L;
N_ND->User.FilesDownloaded=0L;
N_ND->User.BytesUploaded=0L;
N_ND->User.BytesDownloaded=0L;
N_ND->User.PagesMade=0L;
N_ND->User.NukedFiles=0L;
N_ND->User.MsgsRead=0L;
N_ND->User.MsgsWritten=0L;
N_ND->DoorLogOverride=FALSE;
HBBS_SetBBSCols();
HBBS_SetBBSStrings();
// remove file
strcpy(tmpfilename,N_ND->NodeLocation);
strcat(tmpfilename,"Work/SkippedFiles.TXT");
DeleteFile(tmpfilename);
}
void FreeData( void )
{
if (N_ND->User.Valid)
{
N_ND->User.NormalData.TimeUsed+=HBBS_TimeOnline();
HBBS_SaveUserData(&N_ND->User.NormalData);
SaveFileTags();
FreeFileTags(N_ND);
}
N_ND->OnlineStatus=OS_OFFLINE;
}
void GoBBS( void )
{
char tmpstr[1024],confstr[10],datestr[LEN_DATESTR],timestr[LEN_TIMESTR];
V_BIGNUM confnum,loop,loop2;
BOOL ReLogin=FALSE;
do
{
ResetVars();
PutText(str_CLS);
PutText("\033[37;1m");
sprintf(tmpstr,"HNode%dLoginType",N_ND->NodeNum);
switch(N_ND->LoginType)
{
case LOGIN_LOCAL:
ConWriteStr("-=LOCAL LOGIN=-\r\n");
SetVar(tmpstr,"LOCAL",-1 ,GVF_GLOBAL_ONLY);
break;
case LOGIN_REMOTE:
ConWriteStr("-=REMOTE LOGIN=-\r\n");
SetVar(tmpstr,"REMOTE",-1 ,GVF_GLOBAL_ONLY);
break;
}
sprintf(tmpstr,"***********[-CONNECTION ESTABLISHED-]***********[%s*", N_ND->LoginType==LOGIN_REMOTE ? "REMOTE]" : "LOCAL]*");
HBBS_AddToCallersLog(tmpstr);
PutText(ANSI_RESET);
GoSystemDoor("FRONTEND",NULL);
if (N_ND->OnlineStatus==OS_ONLINE)
{
// ok, check to see what the frontend door returned..
strcpy(tmpstr,N_ND->DoorReturn);
if (iposition("HACK",tmpstr)>=0)
{
sprintf(tmpstr,"Hack Attempt - %s",(N_ND->User.Valid ? N_ND->User.CallData.Handle : ""));
HBBS_AddToCallersLog(tmpstr);
// update list of PW Fails..
if (N_ND->User.Valid)
{
Add_Last_PWFail(N_ND->User.CallData.Handle); // add to both...
Add_Last_Caller(N_ND->User.CallData.Handle);
N_ND->Actions[ACTN_HACK]=ACTC_HACK;
}
}
else
if (iposition("FAILED",tmpstr)>=0)
{
// do something.. (update calls log)
sprintf(tmpstr,"Failed Login - %s",(N_ND->User.Valid ? N_ND->User.CallData.Handle : ""));
HBBS_AddToCallersLog(tmpstr);
}
else
if (iposition("LOGGEDIN",tmpstr)>=0)
{
N_ND->Actions[ACTN_CARRIERLOST]=ACTC_CARRIERLOST; // the LOGOUT door ('G') must set this to ACTC_NONE
sprintf(tmpstr,"User logged in, Handle: %s Group: %s Speed: %s",N_ND->User.CallData.Handle,N_ND->User.CallData.Group,N_ND->ConnectBaud);
HBBS_AddToCallersLog(tmpstr);
HBBS_SetAccess();
HBBS_SetWatchTitles();
DOOR_UpdateNodeStatus(UPD_NAME);
DOOR_UpdateNodeStatus(UPD_GROUP);
Add_Last_Caller(N_ND->User.CallData.Handle);
HBBS_GetDate(datestr);
HBBS_GetTime(timestr);
// update the users stats..
HBBS_GetDateStr(tmpstr,N_ND->User.CallData.LastCalledDate);
if (stricmp(tmpstr,datestr)!=0) // date last user called is different from today..
{
N_ND->User.CallData.TimeUsed=0;
N_ND->User.NormalData.TimeUsed=0;
}
N_ND->User.NormalData.CallsMade++;
N_ND->User.CallData.CallsMade++;
N_ND->User.CallData.LastCalledDate=time(NULL);
N_ND->User.NormalData.LastCalledDate=N_ND->User.CallData.LastCalledDate;
// user logged in ok.
sprintf(tmpstr,"HNode%dUser",N_ND->NodeNum);
SetVar(tmpstr,N_ND->User.CallData.Handle,-1,GVF_GLOBAL_ONLY);
LoadFileTags();
if (stricmp(BBSGlobal->LastCalledDate,datestr)==0)
{
BBSGlobal->CallsToday++;
N_ND->CallsToday++;
}
else
{
BBSGlobal->CallsToday=1;
N_ND->CallsToday=1;
}
BBSGlobal->CallsEver++;
strcpy(BBSGlobal->LastCalledDate,datestr);
strcpy(BBSGlobal->LastCalledTime,timestr);
strcpy(N_ND->LastCalledDate,datestr);
strcpy(N_ND->LastCalledTime,timestr);
HBBS_SaveCallsData();
UpdatePrivateData();
UpdateInfoWin(); // updates calls number in the window...
GoSystemDoor("CheckUser","LOGON");
if (stricmp(N_ND->DoorReturn,"LOGIN_DENIED")==0)
{
HBBS_AddToCallersLog("Login Denied by the Check User door!");
}
else
{
sprintf(tmpstr,"Speed_%s",N_ND->ConnectBaud);
GoSystemDoor(tmpstr,NULL);
if (N_ND->OnlineStatus==OS_ONLINE)
{
if (N_ND->User.CallData.Status!=USER_NEW)
{
DisplaySpecialScreen("LoginLogo");
}
if (N_ND->OnlineStatus==OS_ONLINE)
{
GoUserDoor("WALL",NULL);
DisplaySpecialScreen("Bulletin");
// check to see if user want's to keep tagged files from last visit
// if he left with tagged files or lost carrier with files still tagged
GoSystemDoor("CHECKTAGS",NULL);
GoSystemDoor("MAILSCAN",NULL);
sprintf(tmpstr,"HBBS:System/Data/Users/%d/%d.TXT",N_ND->User.CallData.UserID,N_ND->User.CallData.UserID);
DisplayScreen(tmpstr);
confnum=N_ND->User.CallData.LastConf;
if (N_ND->User.CallData.PreferedConf) confnum=N_ND->User.CallData.PreferedConf;
sprintf(confstr,"%d",confnum);
GoSystemDoor("JOINCONF",confstr);
GoSystemDoor("CMDPROMPT",NULL);
// Normally a user is only logged off a) by the sysop pressing F10 or b) by
// typing G at the CMDPROMPT door which then calls the logoff door. but if
// there is a problem with starting the CMDPROMPT door then we'll have to force
// logout the user by trying to run the LOGOUT door, which should logoff the
// user
if (N_ND->OnlineStatus==OS_ONLINE)
{
GoUserDoor("G","SYSTEM");
}
}
}
// do the logoff scripts, but only if a user actually logged in..
// and unlike /X this gets called even if you do a RL
// so all your bulletins actually get updated!
sprintf(tmpstr,"execute HBBS:Scripts/LogOff%ld.script %ld %ld",N_ND->NodeNum,N_ND->NodeNum,N_ND->User.CallData.UserID);
HBBS_RunDOSCMD(tmpstr,FALSE);
sprintf(tmpstr,"execute HBBS:Scripts/LogOff_Global.script %ld %ld",N_ND->NodeNum,N_ND->User.CallData.UserID);
HBBS_RunDOSCMD(tmpstr,FALSE);
}
}
}
else
{
HBBS_AddToCallersLog("A user never logged in. A carrier loss or timeout occured");
}
strcpy(tmpstr,"Actions: ");
loop2=strlen(tmpstr);;
for (loop=0;loop<LEN_ACTIONS;loop++)
{
if (N_ND->Actions[loop]!=ACTC_NONE)
{
tmpstr[loop2++]=N_ND->Actions[loop];
}
}
tmpstr[loop2]=0;
HBBS_AddToCallersLog(tmpstr);
sprintf(tmpstr,"Totals: FU=%d FD=%d BU=%d BD=%d PM=%d NK=%d MR=%d MW=%d",
N_ND->User.FilesUploaded,
N_ND->User.FilesDownloaded,
N_ND->User.BytesUploaded,
N_ND->User.BytesDownloaded,
N_ND->User.PagesMade,
N_ND->User.NukedFiles,
N_ND->User.MsgsRead,
N_ND->User.MsgsWritten);
HBBS_AddToCallersLog(tmpstr);
if (N_ND->User.Valid)
{
sprintf(tmpstr,"Time Online: %ld",HBBS_TimeOnline());
}
HBBS_AddToCallersLog(tmpstr);
HBBS_AddToCallersLog("End Of Session");
FreeData();
if (stricmp(N_ND->DoorReturn,"RELOGIN")==0)
{
ReLogin=TRUE;
N_ND->OnlineStatus=OS_ONLINE;
HBBS_AddToCallersLog("User is re-logging in!");
}
else
{
ReLogin=FALSE;
}
} while(ReLogin);
if (!CarrierLost() && N_ND->LoginType==LOGIN_REMOTE) HangUp();
}
void ResetNodeVars( void )
{
ResetVars();
// this is called just before the await connect door is called..
strcpy(N_ND->ConnectBaud,"--------");
DOOR_UpdateNodeStatus(UPD_ACTION);
DOOR_UpdateNodeStatus(UPD_CPSBAUD);
HBBS_SetAccess(); // clear access levels
}
BOOL CheckModem( void )
{
BOOL retval=TRUE,Done=FALSE;
if (N_ND->SerOK)
{
do
{
SerReset();
if (SerWriteStrWithTimeout("AT\n\r",5,0))
{
Delay(N_ND->NodeDevice.DelayBetweenCmds);
Done=TRUE;
}
else
{
Done=((rtEZRequest("Modem Not Responding","Retry|Cancel",NULL,(struct TagItem *)&rttags,NULL)) ? FALSE : TRUE);
if (Done) retval=FALSE;
}
SerReset();
} while (!Done);
}
return(retval);
}
void AwaitConnect( void )
{
BOOL Error=FALSE;
ResetNodeVars();
if ((N_ND->NodeSettings.UseDevice==FALSE) || ((N_ND->NodeDevice.NullModemCable==FALSE) && CheckModem()) || (N_ND->NodeDevice.NullModemCable==TRUE))
{
do
{
if (!N_ND->NodeDevice.NullModemCable) InitModem();
N_ND->RunningAwait=TRUE;
Error=!GoSystemDoor("AWAIT",NULL); // GoSys returns true if door loads OK
N_ND->RunningAwait=FALSE;
// if local login then put modem offhook so no-one else calls...
if (N_ND->LoginType==LOGIN_LOCAL)
{
if (!N_ND->NodeDevice.NullModemCable || !N_ND->NodeSettings.UseDevice) OffHook();
strcpy(N_ND->ConnectBaud,"LOCAL");
}
DOOR_UpdateNodeStatus(UPD_CPSBAUD);
if (N_ND->LoginType!=LOGIN_NONE)
{
if (HistoryList=HBBS_CreateList())
{
HistoryItems=0;
SendStatus(STAT_ONLINE);
N_ND->OnlineStatus=OS_ONLINE;
GoBBS();
N_ND->LoginType=LOGIN_NONE;
FreeStrList(HistoryList);
HistoryList=NULL;
HistoryItems=0;
HBBS_FreeListNodes(N_ND->OLMList);
N_ND->OLMCount=0;
if (N_ND->NodeFlags & NFLG_OLMSWAITING) N_ND->NodeFlags-=NFLG_OLMSWAITING;
SendStatus(STAT_READY);
}
}
ResetNodeVars();
} while (N_ND->RequestShutdown==FALSE && !Error);
if (!N_ND->NodeDevice.NullModemCable && N_ND->NodeSettings.UseDevice) OffHook();
} // else do error message
if (Error)
{
HBBS_rterror("Error running door, \"Await\"");
}
}
void HandleDoorIOMsg(struct DoorIOMsg *DMsg)
{
DMsg->ReturnVal=0;
switch(DMsg->Status)
{
case DOORIO_WRITECONSTR:
ConWriteStr(DMsg->Data);
break;
case DOORIO_WRITECONDATA:
ConWriteData(DMsg->Data,DMsg->DataLength);
break;
case DOORIO_WRITESERSTR:
SerWriteStr(DMsg->Data);
break;
case DOORIO_WRITESERDATA:
SerWriteData(DMsg->Data,DMsg->DataLength);
break;
case DOORIO_WRITESTR:
PutText(DMsg->Data);
break;
case DOORIO_GETLINE:
DMsg->ReturnVal=Get_Line(DMsg->Flags,DMsg->Data[0],DMsg->Num1,DMsg->Num2,DMsg->OptionStr);
break;
case DOORIO_CHANGECONSOLEMODE:
HBBS_ChangeConsoleMode(DMsg->Num1);
break;
case DOORIO_SYSTEMDOOR:
DMsg->ReturnVal=GoSystemDoor(DMsg->Data,DMsg->OptionStr);
break;
case DOORIO_USERDOOR:
DMsg->ReturnVal=GoUserDoor(DMsg->Data,DMsg->OptionStr);
break;
case DOORIO_HANGUP:
if (N_ND->LoginType==LOGIN_REMOTE) HangUp();
N_ND->OnlineStatus=OS_OFFLINE;
break;
case DOORIO_DISPLAYSCREEN:
DMsg->ReturnVal=DisplayScreen(DMsg->Data);
break;
case DOORIO_DISPLAYSPECIALSCREEN:
DMsg->ReturnVal=DisplaySpecialScreen(DMsg->Data);
break;
case DOORIO_PAUSEPROMPT:
PausePrompt(DMsg->Data,0);
break;
case DOORIO_CONTINUEPROMPT:
DMsg->ReturnVal=ContinuePrompt(DMsg->Data,DMsg->Flags);
break;
case DOORIO_ADDLASTUPLOAD:
Add_Last_Upload(DMsg->Data);
break;
case DOORIO_ADDLASTDOWNLOAD:
Add_Last_Download(DMsg->Data);
break;
case DOORIO_MENUPROMPT:
MenuPrompt(DMsg->Data,DMsg->OptionStr[0]);
break;
case DOORIO_CHECKRAW:
DMsg->ReturnVal=CheckRaw(DMsg->Flags);
break;
}
// a door message MAY be sent to the node without the control or other program
// wanting to be told that the NODE has recived the message, all messages sent
// that DONT want a reply WILL be freed..
if (DMsg->message.mn_ReplyPort)
{
ReplyMsg((struct Message *)DMsg);
}
else
{
FreeVec(DMsg);
}
}